package imu.ming.spring.ioc;

import imu.ming.spring.ioc.AbstractXmlApplicationContext;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;



public class MyClassPathXmlApplicationContext implements imu.ming.spring.ioc.AbstractXmlApplicationContext {
    //定义beanContainer保存bean,key-value
    private Map<String, Object> beanContainer = new HashMap<String, Object>();


    public MyClassPathXmlApplicationContext(String path) {
        //使用dom4j解析xml文件读取bean标签，将对象创建出来用id为键，对象为值保存到容器中
        SAXReader reader = new SAXReader();
        try {
            //通过反射机制获取资源文件的路径
            URL url = AbstractXmlApplicationContext.class.getClassLoader().getResource(path);
            //读取xml文件
            Document document = reader.read(url);
            //获取根便签
            Element rootElement = document.getRootElement();
            //读取bean标签，得到对应对象集合
            List<Element> beans = rootElement.elements("bean");
            System.out.println("beans"+beans);
            //获取bean标签中的id作为键，class对象值，并保存到容器中
            for (Element b : beans) {
                //获取id键
                String key = b.attributeValue("id");
                //获取class值
                String value = b.attributeValue("class");
                if(Objects.nonNull(value)) {
                    //存入容器中
                    System.out.println("class  "+value);
                    beanContainer.put(key, Class.forName(value).newInstance());
                }
            }
            //根据constructor-arg标签定义的依赖关系完成依赖注入
            for (Element b : beans) {

                if (b.elements("property").size() > 0){
                    //获取bean下的property标签
                    List<Element> properties = b.elements("property");
                    for (Element p : properties) {
                        //需要被赋值的属性名称
                        String pName = p.attributeValue("name");
                        System.out.println("pName  "+pName);
                        //该属性需要赋值的对象在容器里的id
                        String pBean = p.attributeValue("ref");
                        System.out.println("pBean  "+pBean);
//                        String pBean = p.element("ref").attributeValue("bean");
                        //从容器中拿到被依赖的对象
                        Object refObject = beanContainer.get(pBean);

                        //根据bean标签拿到正在循环的这个bean标签的id
                        String key = b.attributeValue("id");
                        //从容器中取出依赖方对象
                        System.out.println("key"+key);
                        Object object = beanContainer.get(key);
                        //获取依赖方的字节码信息
                        Class c = object.getClass();
                        System.out.println("c  "+c);
                        //获取成员变量对应的set方法
                        System.out.println("pName.substring(0,1).toUpperCase() + pName.substring(1)");
                        System.out.println("set"+pName.substring(0,1).toUpperCase() + pName.substring(1));
                        System.out.println("refObject.getClass() "+refObject.getClass());

                        //因为这里refObject.getClass()是LiuDeHua，但是原接口参数是接口GeLi，所以必须获得getInterfaces()来寻找方法
                        final Method setMethod = c.getMethod("set" +
                                //将set方法第一个字母转大写
                                pName.substring(0,1).toUpperCase() + pName.substring(1),refObject.getClass().getInterfaces());
//                        final Method setMethod = c.getMethod("cityGateAsk");

//                        //创建对象
                        setMethod.invoke(object,refObject);
                        beanContainer.put(key,object);
                    }
                }


            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Object getBean(String id) {
        return beanContainer.get(id);
    }
}
